package com.fg.util;

import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ValidPattern {
	private static String[] nonValidSymbol_forName = {
		"\\&", "\\~", "\\`", "\\!", "\\@", "\\#", "\\$", "\\%", "\\^", "\\*", 
		"\\(", "\\)", "\\+", "\\=", "\\{", "\\}", "\\[", "\\]", "\\|", "\\\\",
		"\\:", "\\;", "\\\"", "\\<", "\\>", "\\?", "\\/"
	};
	
	private static String[] nonValidSymbol_forName_ascii = {
		"&#38;", "&#126;", "&#96;", "&#33;", "&#64;", "&#35;", "&#36;", "&#37;", "&#94;", "&#42;", 
		"&#40;", "&#41;", "&#43;", "&#61;", "&#123;", "&#125;", "&#91;", "&#93;", "&#124;", "&#92;",
		"&#58;", "&#59;", "&#147;", "&#60;", "&#62;", "&#63;", "&#47;"
	};
	
	private static PairStringArray html_special_characters;
	
	private static String email_regex;
	
	private static String password_regex;
	public static final int MIN_PASSWORD_LENGTH = 5;
	public static final int MAX_PASSWORD_LENGTH = 14;
	
	private static String name_regex;
	public static final int MIN_NAME_LENGTH = 3;
	public static final int MAX_NAME_LENGTH = 20;
	
	private static String message_regex;
	public static final int MIN_MESSAGE_LENGTH = 1;
	public static final int MAX_MESSAGE_LENGTH = 3000;
	
	private static String date_regex;
	
	private static String time_regex; 
	
	static {
		initEmailRegex();
		initPasswordRegex();
		initNameRegex();
		initMessageRegex();
		initDateRegex();
		initTimeRegex();
	}
	
	/**
	 * 일/월/년(24/3/2010) date 정규표현식 초기화 메소드
	 */
	private static void initDateRegex() {
		date_regex = "^\\d{1,2}(\\/)\\d{1,2}(\\/)\\d{4}$";
	}
	
	/**
	 * 시:분am or pm(7:34pm) time 정규표현식 초기화 메소드
	 */
	private static void initTimeRegex() {
		time_regex = "^\\d{1,2}(\\:)\\d{1,2}(am|pm)$";
	}
	
	/**
	 * email 정규표현식 초기화 메소드 
	 */
	private static void initEmailRegex() {
		email_regex = "^((\\w|[\\-\\.])+)@((\\w|[\\-\\.])+)\\.([A-Za-z]+)$";
	}
	
	/**
	 * password 정규표현식 초기화 메소드
	 */
	private static void initPasswordRegex() {
		password_regex = "(\\w|[\\-\\.]){" + MIN_PASSWORD_LENGTH + "," + MAX_PASSWORD_LENGTH + "}";
	}
	
	/**
	 * name 정규표현식 초기화 메소드
	 */
	private static void initNameRegex() {
		StringBuffer name_regex_buf = new StringBuffer();
		name_regex_buf.append("[^\\f\\n\\r\\t\\v");
		for(int i=0; i < nonValidSymbol_forName.length; i++) {
			name_regex_buf.append(nonValidSymbol_forName[i]);
		}
		name_regex_buf.append("]{" + MIN_NAME_LENGTH + "," + MAX_NAME_LENGTH + "}");
		name_regex = name_regex_buf.toString();
	}
	
	/**
	 * message 정규표현식 초기화 메소드
	 */
	private static void initMessageRegex() {
		message_regex = "";

		html_special_characters = new PairStringArray();
		html_special_characters.add("&", "&amp;");
		html_special_characters.add("\"", "&quot;");
		html_special_characters.add("'", "&#039;");
		html_special_characters.add("<", "&lt;");
		html_special_characters.add(">", "&gt;");
	}
	

	public static boolean validateDate(String input) {
		return Pattern.compile(date_regex).matcher(input).matches();
	}
	
	public static boolean validateTime(String input) {
		return Pattern.compile(time_regex).matcher(input).matches();
	}
	
	
	public static boolean validateEmail(String input) {
		return Pattern.compile(email_regex).matcher(input).matches();
	}
	
	
	public static boolean validatePassword(String input) {
		return Pattern.compile(password_regex).matcher(input).matches();
	}
	
	
	public static boolean validateName(String input) {
		return Pattern.compile(name_regex).matcher(input).matches();
	}
	
	/**
	 * UTF-8형식으로 인코딩한다
	 * @param sourceStr
	 */
	public static void encodedUTF8(String sourceStr) {
		try {
			sourceStr = URLEncoder.encode(sourceStr, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * UTF-8형식으로 디코딩한다
	 * @param array
	 */
	public static void decodeUTF8(String encodedStr) {
		try{
			encodedStr = URLDecoder.decode(encodedStr, "UTF-8");
		}catch( Exception e){
			e.printStackTrace();
		}
	}
	
	/**
	 * 메시지를 원래의 문자로 디코드한다.
	 * @param input
	 * @return
	 */
	public static String decodeMessage(String input) {
		String output = new String(input);
		for (int i=0; i<html_special_characters.length(); i++) {
			output = output.replace(html_special_characters.getValue(i), html_special_characters.getKey(i));
		}
		return output;
	}
	
	/**
	 * 메시지를 html형식에 맞는 문자로 인코딩한다.
	 * @param input
	 * @return
	 */
	public static String encodeMessage(String input) {
		String output = new String(input);
		for (int i=0; i<html_special_characters.length(); i++) {
			output = output.replace(html_special_characters.getKey(i), html_special_characters.getValue(i));
		}
		return output;
	}
	
	/**
	 * Text에 URL을 찾아서 HTML Link로 만들어준다. 
	 * @param text
	 * @return
	 */
	public static String replaceURLtoLink(String text){
		  String regex = "([\\p{Alnum}]+)://([a-z0-9.\\-&/%=?:@#$(),.+;~\\_]+)";
		  Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
		  Matcher m = p.matcher(text);
		  String s = m.replaceAll("<a href='http://$2' target=_blank>http://$2</a>");
		  return s;
	}
	
	public static String replaceNewLine(String text){
		  String regex = "/\n/g";
		  Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
		  Matcher m = p.matcher(text);
		  String s = m.replaceAll("<br/>");
		  return s;
	}
	
	public static boolean validateMessage(String input) {
		String output = null;
		output = decodeMessage(input);
		if (output.length() < MIN_MESSAGE_LENGTH || output.length() > MAX_MESSAGE_LENGTH) return false;
		output = encodeMessage(output);
		return true;
	}
	
	/**
	 * 메시지안를 웹에 맞는 형식으로 변경한다.
	 * 변환되어서 넘어온 값이 있더라도 원래의 문자로 변환을 해줘서 원본을 복구하고,
	 * 전체적으로 다시 웹에 맞는 형식으로 변경한다.
	 * @param input
	 * @return
	 */
	public static String replaceMessage(String input) {
		String output = null;
		output = decodeMessage(input);
		output = encodeMessage(output);
		output = replaceURLtoLink(output);
		output = output.replaceAll("\n", "<br/>");
		System.out.println(output);
		return output;
	}
}

class PairStringArray {
	private ArrayList<String> key;
	private ArrayList<String> value;
	
	private int length;
	
	public PairStringArray() {
		key = new ArrayList<String>();
		value = new ArrayList<String>();
		length = 0;
	}
	
	public void add(String key, String value) {
		this.key.add(key);
		this.value.add(value);
		length++;
	}
	
	public String getKey(int index) {
		return key.get(index);
	}
	
	public String getValue(int index) {
		return value.get(index);
	}
	
	public void remove(int index) {
		key.remove(index);
		value.remove(index);
		length--;
	}
	
	public void clear() {
		key.clear();
		value.clear();
		length = 0;
	}
	
	public int length() {
		return length;
	}
}
